from Tkinter import *
import Image
from ImageTk import PhotoImage
import tkFont
import os, sys
from random import Random

class Digits:

  image = Image.open(os.path.join("data", "binaryalphadigs.jpg"))
  N = 39
  digits = "0123456789abcdefghijklmnopqrstuvwxyz".upper()
  random = Random()
  
  def __init__(self):
    pass
    
  def get(self, i=None, j=None):
    image, digits, N = self.image, self.digits, self.N
    if i == None:
      i = self.random.randint(0, N-1)
    if j == None:
      j = self.random.randint(0, len(digits)-1)
    w, h = image.size
    w /= N
    h /= len(digits)
    return (self.digits[j], self.image.crop((i*w, j*h, (i+1)*w, (j+1)*h)))

class UI(Frame):
  random = Random()
  def __init__(self, root=None, **F):
    Frame.__init__(self, **F)
    if not root:
      root = Tk()
      self.w, self.h = root.winfo_screenwidth(), root.winfo_screenheight()
      root.overrideredirect(1)
      root.geometry("%dx%d+0+0" % (self.w, self.h))
      root.focus_set()
      root.bind('<Escape>', lambda e: root.quit())

    self.root = root
    self.config(width=self.w, height=self.h)
    self.canvas = Canvas(self, width = self.w, height=self.h)
    self.image = None # holds the photoimage instance
    self.grid()
    self.canvas.grid()
    canvas = self.canvas
    canvas.create_rectangle((0,0), (self.w, self.h), fill="#000000")
    self.draw_network()
    
  def draw_image(self, image):
    w, h = image.size
    if not self.image:
      self.image = PhotoImage(image.resize((w*5, h*5)))
      self.canvas.create_image(self.w * 0.1, (self.h-h) * 0.5, anchor=NW, image=self.image, tag='beautify_pix')
    else:
      self.image = PhotoImage(image.resize((w*5, h*5)))
      self.canvas.itemconfigure('beautify_pix', image=self.image)

  def draw_letter(self, letter, error=False):
    try:
      getattr(self, 'letter')
    except:
      self.letter = self.canvas.create_text(
      self.w * 0.8, self.h / 2, text = letter, font=tkFont.Font(family="Georgia", size=128), fill="#FFFFFF")
    else:
        self.canvas.itemconfigure(self.letter, text = letter, fill=("#FF0000" if error else "#FFFFFF"))
      
  def draw_network(self, image=None):
    X = 500
    X1 = 700
    X2 = 900
    rad = 5
    num = 100
    Y0 = self.h * 0
    Y1 = self.h
    Y0x = self.h * 0.1
    Y1x = self.h * 0.9
    radx = 10
    numx = 50
    dY = (Y1-Y0-2*rad)/num
    dYx = (Y1x-Y0x-2*radx)/numx 
    
    if image == None:
      self.inodes = []
      self.xnodes = []
      for i in range(num):
        x0, y0 = X, (Y0+i*dY)
        self.inodes.append(self.canvas.create_rectangle(x0, y0, x0+rad*5, y0+rad, outline="#FFFFFF"))
        
      for j in range(numx):
        x0, y0 = X1, (Y0x+j*dYx)
        self.xnodes.append(self.canvas.create_oval(x0, y0, x0+radx, y0+radx, outline="#FFFFFF"))
      
      for i in range(10, num, 30):
        for j in range(10, numx, 10):
          x0, y0 = X+rad*5, (Y0+i*dY)
          x1, y1 = X1, (Y0x+j*dYx)
          self.canvas.create_line(x0,y0, x1, y1, fill="#FFFFFF");
          
    else:
      w, h = image.size
      canvas = self.canvas
      for k in range(num):
        i, j = k % w, k / w
        if image.getpixel((i,j)) > 100:
          canvas.itemconfigure(self.inodes[k], fill="#FFFFFF")
        else:
          canvas.itemconfigure(self.inodes[k], fill="#000000")
      for k in range(numx):
        c = hex(self.random.randint(10, 255))[2:]
        c = "#%s%s%s" % (c, c, c)
        canvas.itemconfigure(self.xnodes[k], fill=c)

class Controller:
  
  def __init__(self, ui, digits):
    self.ui = ui
    self.digits = digits
    self.paused = False
    root = self.ui.root
    root.bind('<Escape>', lambda e: root.quit())
    root.bind('<KeyPress-space>', lambda e: self.toggle_paused())
    self.refresh()
    self.ui.root.mainloop()
  
  def toggle_paused(self):
    self.paused = not self.paused
    if not self.paused:
      self.refresh()
      
  def refresh(self):
    (letter, im) = self.digits.get()
    self.ui.draw_image(im)
    self.ui.draw_network(im)
    if self.digits.random.random() < 0.1:
      letter = self.digits.random.choice(self.digits.digits)
      self.ui.draw_letter(letter, True)
    else:
      self.ui.draw_letter(letter)
    self.ui.canvas.update()
    if not self.paused:
      self.ui.after(500, self.refresh)
  
if __name__ == '__main__':
  root = Tk()
  w, h = root.winfo_screenwidth(), root.winfo_screenheight()
  root.overrideredirect(1)
  root.geometry("%dx%d+-1+-1" % (w, h))
  root.focus_set()
  Controller(UI(), Digits())